package com.apobates.forum.thrones.admin.controller;

import com.apobates.forum.core.ImageIOMeta;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicCategory;
import com.apobates.forum.core.entity.TopicConfig;
import com.apobates.forum.core.entity.TopicTag;
import com.apobates.forum.core.entity.proxy.PostsReplica;
import com.apobates.forum.core.entity.proxy.TopicReplica;
import com.apobates.forum.core.service.BoardService;
import com.apobates.forum.core.service.PostsService;
import com.apobates.forum.core.service.TopicCategoryService;
import com.apobates.forum.core.service.TopicConfigService;
import com.apobates.forum.core.service.TopicService;
import com.apobates.forum.core.service.TopicTagService;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.thrones.admin.controller.form.TopicConfigForm;
import com.apobates.forum.thrones.admin.controller.form.TopicModifyForm;
import com.apobates.forum.thrones.admin.controller.form.TopicPublishForm;
import com.apobates.forum.thrones.admin.exception.ResourceNotFoundException;
import com.apobates.forum.utils.lang.CommonBean;
import com.apobates.forum.utils.FrontPageURL;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.lang.EnumArchitecture;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.PageRequest;
import com.apobates.forum.utils.persistence.Pageable;
import java.util.List;
import java.util.Optional;

/**
 * 话题控制器
 *
 * @author xiaofanku
 * @since 20190407
 */
@Controller
@RequestMapping(value = "/topic")
public class AdminTopicController {
    @Autowired
    private TopicService topicService;
    @Autowired
    private TopicTagService topicTagService;
    @Autowired
    private TopicCategoryService topicCategoryService;
    @Autowired
    private PostsService postsService;
    @Autowired
    private TopicConfigService topicConfigService;
    @Autowired
    private BoardService boardService;
    @Autowired
    private ImageIOMeta imageIOMeta;
    @Value("${site.pageSize}")
    private int pageSize;
    
    @GetMapping(path = "/")
    public String listPage(
            @RequestParam(name = "board", required = false, defaultValue = "0") long boardId,
            HttpServletRequest request,
            Model model) {
        Stream<Topic> rs = (boardId > 0) ? topicService.getRecentForBoard(boardId, pageSize) : topicService.getRecentIgnoreCondition(pageSize);
        model.addAttribute("rs", rs.collect(Collectors.toList()));
        return "admin/topic/index";
    }
    
    @GetMapping(path = "/edit")
    public String editForm(
            @RequestParam("id") long id,
            HttpServletRequest request,
            Model model) {
        Topic topicObj = topicService.get(id).orElseThrow(()->new ResourceNotFoundException("话题不存在或暂时无法访问"));
        //禁止编辑的
        if (TopicCategory.isForbidCategoryValue().contains(topicObj.getTopicCategoryValue())) {
            throw new ResourceNotFoundException("话题所在的分类禁止二次编辑");
        }
        PostsReplica content = postsService.getPostsContentForEditByTopic(id, imageIOMeta).orElseThrow(()->new ResourceNotFoundException("内容不存在或暂时无法访问"));
        String words = topicTagService.getAllBy(id).stream().map(TopicTag::getNames).collect(Collectors.joining(","));
        //
        TopicModifyForm form = new TopicModifyForm();
        form.setTitle(topicObj.getTitle());
        form.setWords(words);
        form.setRecord(id);
        form.setContent(content.getContent());
        model.addAttribute("form", form);
        return "admin/topic/edit";
    }
    
    @PostMapping(path = "/edit")
    public String editAction(
            @ModelAttribute("form") TopicModifyForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, form.getToken());
        Boolean symbol = topicService.edit(
                form.getLongRecord(),
                form.getTitle(),
                form.getContent(),
                form.getWordsArray(),
                imageIOMeta,
                aec).orElse(false);
        
        if (symbol) {
            return "redirect:/topic/" + form.getLongRecord() + ".xhtml";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "编辑话题操作失败");
        return "admin/topic/edit";
    }
    //新话题
    @GetMapping(path = "/publish")
    public String createTopicForm(
            @RequestParam(name = "volumes", required = false, defaultValue = "-1") int volumesId,
            @RequestParam(name = "board", required = false, defaultValue = "0") long boardId,
            HttpServletRequest request,
            Model model) {
        TopicPublishForm form = new TopicPublishForm();
        form.setBoard(boardId + "");
        form.setVolumes(volumesId + "");
        model.addAttribute("form", form);
        return "admin/topic/create";
    }
    
    @PostMapping(path = "/publish")
    public String createTopicAction(
            @ModelAttribute("form") TopicPublishForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        int volumesId = form.getIntegerVolumes();
        long boardId = form.getLongBoard();
        TopicCategory tc = topicCategoryService.get(form.getCategory()).orElse(TopicCategory.empty());
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, form.getToken());
        //
        if (boardId > 0 && volumesId >= 0) { //有可能在默认分组中
            long data = topicService.create(
                    volumesId,
                    boardId,
                    tc.getNames(), tc.getValue(),
                    form.getTitle(),
                    form.getContent(),
                    form.getWordsArray(),
                    imageIOMeta,
                    aec);
            if (data > 0) {
                return "redirect:/topic/" + data + ".xhtml";
            }
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "发布话题操作失败");
        return "admin/topic/create";
    }
    
    @GetMapping(path = "/config")
    public String topicConfigForm(
            @RequestParam("id") long topicId,
            HttpServletRequest request,
            Model model) {
        TopicConfig c = topicConfigService.getByTopicId(topicId).orElse(TopicConfig.empty());
        TopicConfigForm form = new TopicConfigForm();
        form.setPrivacy(c.isPrivacy());
        form.setReply(c.isReply());
        form.setNotify(c.isNotify());
        form.setAtomPoster(c.isAtomPoster());
        form.setWriteMinInterrupt(c.getWriteMinInterrupt() + "");
        //r
        form.setReadMinScore(c.getReadMinScore() + "");
        form.setReadLowMemberGroup(c.getReadLowMemberGroup().getSymbol() + "");
        form.setReadLowMemberRole(c.getReadLowMemberRole().getSymbol() + "");
        form.setReadLowMemberLevel(c.getReadLowMemberLevel() + "");
        //w
        form.setWriteMinScore(c.getWriteMinScore() + "");
        form.setWriteLowMemberGroup(c.getWriteLowMemberGroup().getSymbol() + "");
        form.setWriteLowMemberRole(c.getWriteLowMemberRole().getSymbol() + "");
        form.setWriteLowMemberLevel(c.getWriteLowMemberLevel() + "");
        //
        form.setRecord(c.getId());
        form.setTopicId(c.getTopicId() + "");
        model.addAttribute("form", form);
        //
        model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
        model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
        return "admin/topic/config";
    }
    
    @PostMapping(path = "/config")
    public String topicConfigAction(
            @ModelAttribute("form") TopicConfigForm form,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        long topicId = form.getLongTopicId();
        if (topicId == 0) {
            model.addAttribute("form", form);
            model.addAttribute("errors", "话题参数丢失");
            //
            model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
            model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
            return "admin/topic/config";
        }
        TopicConfig config = new TopicConfig();
        config.setId(form.getLongRecord());
        config.setTopicId(topicId);
        config.setPrivacy(form.getBooleanPrivacy());
        config.setReply(form.getBooleanReply());
        config.setNotify(form.getBooleanNotify());
        config.setAtomPoster(form.getBooleanAtomPoster());
        config.setWriteMinInterrupt(form.getIntegerWriteMinInterrupt());
        //r
        config.setReadMinScore(form.getIntegerReadMinScore());
        MemberGroupEnum rmg = EnumArchitecture.getInstance(form.getIntegerReadLowMemberGroup(), MemberGroupEnum.class).orElse(MemberGroupEnum.GUEST);
        config.setReadLowMemberGroup(rmg);
        MemberRoleEnum rmr = EnumArchitecture.getInstance(form.getIntegerReadLowMemberRole(), MemberRoleEnum.class).orElse(MemberRoleEnum.NO);
        config.setReadLowMemberRole(rmr);
        config.setReadLowMemberLevel(form.getIntegerReadLowMemberLevel());
        //w
        config.setWriteMinScore(form.getIntegerWriteMinScore());
        MemberGroupEnum wmg = EnumArchitecture.getInstance(form.getIntegerWriteLowMemberGroup(), MemberGroupEnum.class).orElse(MemberGroupEnum.CARD);
        config.setWriteLowMemberGroup(wmg);
        MemberRoleEnum wmr = EnumArchitecture.getInstance(form.getIntegerWriteLowMemberRole(), MemberRoleEnum.class).orElse(MemberRoleEnum.NO);
        config.setWriteLowMemberRole(wmr);
        config.setWriteLowMemberLevel(form.getIntegerWriteLowMemberLevel());
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, form.getToken());
        Optional<Boolean> symbol = topicService.editTopicConfig(
                form.getLongTopicId(),
                config,
                form.getLongRecord(),
                aec);
        if (symbol.orElse(false)) {
            return "redirect:/topic/" + config.getTopicId() + ".xhtml";
        }
        model.addAttribute("form", form);
        model.addAttribute("errors", "更新话题的配置文件失败");
        //
        model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
        model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
        return "admin/topic/config";
    }
    //版块下的话题
    @GetMapping(path = "/list/{id}.xhtml")
    public String topicHome(
            @PathVariable("id") long boardId,
            @RequestParam(value = "p", required = false, defaultValue = "1") int page,
            HttpServletRequest request,
            Model model) {
        Board board = boardService.get(boardId).orElseThrow(()->new ResourceNotFoundException("版块不存在或暂时无法访问"));
        FrontPageURL fpbuild = new FrontPageURL(request.getContextPath() + "/topic/list/" + boardId + ".xhtml").addPageSize("number", pageSize);
        Pageable pr = new PageRequest(page, fpbuild.getPageSize());
        Page<TopicReplica> rs = topicService.getAll(boardId, pr);
        model.addAttribute("rs", rs.getResult().collect(Collectors.toList()));
        model.addAttribute("pageData", fpbuild.toPageData(pr, rs.getTotalElements()));
        model.addAttribute("board", board);
        return "admin/topic/board";
    }
    
    /*话题统计
	@GetMapping(path="/stats")
	public String getTopicStats(
			@RequestParam("id")long topicId, 
			@RequestParam("volume")int boardGroupId, 
			@RequestParam("board")long boardId, 
			HttpServletRequest request, 
			Model model){
		TopicStats ts = topicStatsService.getByTopic(topicId).getOrElse(new TopicStats(topicId, boardGroupId, boardId));
		model.addAttribute("stats", ts);
		return "admin/topic/stats";
	}*/
    //锁定话题
    @PostMapping(path = "/lock", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TipMessage lockTopicAction(
            @RequestParam("id") long topicId,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, "");
        return TipMessage.Builder.take(()->topicService.lock(topicId, aec)).success("成功锁定话题").error("操作失败");
    }
    //锁定话题
    @PostMapping(path = "/lock/remove", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TipMessage removeLockTopicAction(
            @RequestParam("id") long topicId,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, "");
        return TipMessage.Builder.take(()->topicService.releaseLock(topicId, aec)).success("成功解锁话题").error("操作失败");
    }
    //删除话题
    @PostMapping(path = "/remove", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TipMessage removeTopicAction(
            @RequestParam("id") long topicId,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, "");
        return TipMessage.Builder.take(()->topicService.remove(topicId, aec)).success("话题删除成功").error("操作失败");
    }
    //置顶话题
    @PostMapping(path = "/top", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TipMessage setTopTopicAction(
            @RequestParam("id") long topicId,
            MemberSessionBean mbean,
            HttpServletRequest request,
            Model model) {
        ActionEventCulpritor aec = AdminHomeController.getActionCulpritor(mbean.getMid(), mbean.getNickname(), request, "");
        return TipMessage.Builder.take(()->topicService.editTop(topicId, aec)).success("话题置顶成功").error("操作失败");
    }
    
    @GetMapping(path = "/{id}.xhtml")
    public String topicViewPage(
            @PathVariable("id") long topicId,
            HttpServletRequest request,
            Model model) {
        TopicReplica topic = topicService.getTopicContentAndStats(topicId, imageIOMeta).orElseThrow(()->new ResourceNotFoundException("话题不存在或暂时无法访问"));
        //标签
        List<TopicTag> tags = topicTagService.getAllBy(topicId);
        topic.getTages().addAll(tags);
        model.addAttribute("topic", topic);
        return "admin/topic/view";
    }
    //加载话题的标题
    @GetMapping(path = "/title", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public CommonBean getTopicTitle(
            @RequestParam("id") long id,
            HttpServletRequest request,
            Model model) {
        if (id == 0) {
            return new CommonBean(0, "所有");
        }
        String title = topicService.get(id).map(Topic::getTitle).orElse("话题");
        return new CommonBean(id, title);
    }
    //Key=SmileyTheme.directNames, Value=SmileyTheme.title
}